package com.example.huadu_server.landlord.service.impl;

import com.example.huadu_server.appointment.entity.Appointment;
import com.example.huadu_server.config.Response;
import com.example.huadu_server.landlord.entity.LandlordSchedule;
import com.example.huadu_server.landlord.mapper.LandlordScheduleMapper;
import com.example.huadu_server.landlord.service.LandlordScheduleService;
import com.example.huadu_server.appointment.mapper.AppointmentMapper;
import com.example.huadu_server.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class LandlordScheduleServiceImpl implements LandlordScheduleService {

    @Autowired
    private LandlordScheduleMapper landlordScheduleMapper;

    @Autowired
    private AppointmentMapper appointmentMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String senderEmail;

    /**
     * 根据房东ID获取房东的档期信息
     * @param landlordId
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public List<LandlordSchedule> getSchedulesForLandlord(int landlordId, Date startDate, Date endDate) {
        // 【1】先固定日期范围：明天到未来 7 天（共 7 天）
        Calendar calStart = Calendar.getInstance();
        calStart.set(Calendar.HOUR_OF_DAY, 0);
        calStart.set(Calendar.MINUTE, 0);
        calStart.set(Calendar.SECOND, 0);
        calStart.set(Calendar.MILLISECOND, 0);
        calStart.add(Calendar.DAY_OF_MONTH, 1); // 明天开始

        Calendar calEnd = (Calendar) calStart.clone();
        calEnd.add(Calendar.DAY_OF_MONTH, 6); // 明天 + 6 天 => 共 7 天

        Date newStartDate = calStart.getTime();
        Date newEndDate = calEnd.getTime();

        // 【2】查询数据库中 [newStartDate, newEndDate] 范围内已存在的档期
        List<LandlordSchedule> schedules = landlordScheduleMapper
                .selectSchedulesByLandlordIdAndDateRange(landlordId, newStartDate, newEndDate);

        // 【3】构建日期 -> 档期列表映射，方便判断当天是否已有档期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Map<String, List<LandlordSchedule>> dateMap = new HashMap<>();
        for (LandlordSchedule sch : schedules) {
            String dateStr = sdf.format(sch.getScheduleDate());
            dateMap.computeIfAbsent(dateStr, k -> new ArrayList<>()).add(sch);
        }

        // 【4】定义每天 6 个时段
        String[][] timeSlots = {
                {"09:00:00", "11:00:00"},
                {"11:00:00", "13:00:00"},
                {"13:00:00", "15:00:00"},
                {"15:00:00", "17:00:00"},
                {"17:00:00", "19:00:00"},
                {"19:00:00", "21:00:00"}
        };

        // 【5】从 newStartDate ~ newEndDate，逐天检测是否有档期，没有则插入 6 个时段
        while (!calStart.after(calEnd)) {
            Date currentDate = calStart.getTime();
            String dateStr = sdf.format(currentDate);

            // 如果当天无档期记录，则补齐 6 个时段
            if (!dateMap.containsKey(dateStr)) {
                for (String[] slot : timeSlots) {
                    LandlordSchedule schedule = new LandlordSchedule();
                    schedule.setLandlordId(landlordId);
                    schedule.setScheduleDate(new java.sql.Date(currentDate.getTime()));
                    schedule.setStartTime(java.sql.Time.valueOf(slot[0]));
                    schedule.setEndTime(java.sql.Time.valueOf(slot[1]));
                    schedule.setStatus("available");
                    landlordScheduleMapper.insert(schedule);
                }
            }
            calStart.add(Calendar.DAY_OF_MONTH, 1); // 下一天
        }

        // 【6】补齐完毕后，再查一次最终档期并返回
        schedules = landlordScheduleMapper.selectSchedulesByLandlordIdAndDateRange(landlordId, newStartDate, newEndDate);

        // 获取档期后进行过期判断
        Date currentDate = new Date();
        for (LandlordSchedule schedule : schedules) {
            if (schedule.getStatus().equals("available") && schedule.getScheduleDate().before(currentDate)) {
                schedule.setStatus("expired");
                landlordScheduleMapper.updateById(schedule);  // 更新状态为expired
            }
        }

        return schedules;
    }

    /**
     * 获取房东的档期列表
     * @param landlordId
     * @param status
     * @param isFuture
     * @return
     */
    @Override
    public Response<Map<String, Object>> getLandlordSchedules(Integer landlordId, String status, boolean isFuture) {
        try {
            List<LandlordSchedule> schedules;

            if (isFuture) {
                // 1. 先查询现有的未来档期
                schedules = landlordScheduleMapper.selectFutureSchedulesByLandlordId(landlordId, status);

                // 2. 自动补齐从明天开始未来7天的档期
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.DAY_OF_MONTH, 1); // 从明天开始
                Date startDate = cal.getTime();
                cal.add(Calendar.DAY_OF_MONTH, 6); // 明天+6天=7天
                Date endDate = cal.getTime();

                // 定义每天6个时段
                String[][] timeSlots = {
                        {"09:00:00", "11:00:00"},
                        {"11:00:00", "13:00:00"},
                        {"13:00:00", "15:00:00"},
                        {"15:00:00", "17:00:00"},
                        {"17:00:00", "19:00:00"},
                        {"19:00:00", "21:00:00"}
                };

                // 3. 检查这7天是否有档期，没有则补齐
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Map<String, Boolean> dateExistsMap = new HashMap<>();

                // 先标记哪些日期已经有档期
                for (LandlordSchedule sch : schedules) {
                    String dateStr = sdf.format(sch.getScheduleDate());
                    dateExistsMap.put(dateStr, true);
                }

                // 从明天开始循环到未来7天
                Calendar calStart = Calendar.getInstance();
                calStart.setTime(startDate);
                Calendar calEnd = Calendar.getInstance();
                calEnd.setTime(endDate);

                while (!calStart.after(calEnd)) {
                    Date currentDate = calStart.getTime();
                    String currentDateStr = sdf.format(currentDate);

                    // 如果这一天没有档期记录，则补齐6个时段
                    if (!dateExistsMap.containsKey(currentDateStr)) {
                        for (String[] slot : timeSlots) {
                            LandlordSchedule schedule = new LandlordSchedule();
                            schedule.setLandlordId(landlordId);
                            schedule.setScheduleDate(new java.sql.Date(currentDate.getTime()));
                            schedule.setStartTime(java.sql.Time.valueOf(slot[0]));
                            schedule.setEndTime(java.sql.Time.valueOf(slot[1]));
                            schedule.setStatus("available");
                            landlordScheduleMapper.insert(schedule);
                        }
                    }
                    calStart.add(Calendar.DAY_OF_MONTH, 1);
                }

                // 4. 重新查询补齐后的档期列表
                schedules = landlordScheduleMapper.selectFutureSchedulesByLandlordId(landlordId, status);
            } else {
                schedules = landlordScheduleMapper.selectAllSchedulesByLandlordId(landlordId, status);
            }

            // 获取档期后进行过期判断
            Date currentDate = new Date();
            for (LandlordSchedule schedule : schedules) {
                if (schedule.getStatus().equals("available") && schedule.getScheduleDate().before(currentDate)) {
                    schedule.setStatus("expired");
                    landlordScheduleMapper.updateById(schedule);  // 更新状态为expired
                }
            }

            // 查询总记录数
            int total = landlordScheduleMapper.countSchedulesByLandlordId(landlordId, status, isFuture);

            // 将结果转换为 Map 返回
            Map<String, Object> result = new HashMap<>();
            result.put("total", total);
            result.put("schedules", schedules);

            return new Response<>(200, "查询成功", result);
        } catch (Exception e) {
            return new Response<>(500, "查询失败：" + e.getMessage(), null);
        }
    }
    /**
     * 更新档期状态
     * @param scheduleId 档期ID
     * @param newStatus  目标状态（例如设置为 "forbid"）
     * @param landlordId 当前房东ID（必须拥有该档期）
     * @return
     */
    @Override
    @Transactional
    public Response<String> updateScheduleStatus(Integer scheduleId, String newStatus, int landlordId, String rejectReason) {
        // 查询档期
        LandlordSchedule schedule = landlordScheduleMapper.selectById(scheduleId);
        if (schedule == null) {
            // 档期不存在
            return new Response<>(404, "档期不存在", null);
        }

        // 检查房东是否是该档期的所有者
        if (!schedule.getLandlordId().equals(landlordId)) {
            // 如果房东ID不匹配，返回权限不足
            return new Response<>(403, "您无权修改该档期", null);
        }

        // 如果状态为"booked"且更新为"unavailable"，需要提供拒绝理由并通知用户
        if (schedule.getStatus().equals("booked") && "forbid".equals(newStatus)) {
            if (rejectReason == null || rejectReason.isEmpty()) {
                // 如果拒绝理由为空，返回错误
                return new Response<>(400, "拒绝理由不能为空", null);
            }

            // 获取与该档期相关的所有预约记录
            List<Appointment> appointments = appointmentMapper.selectByScheduleId(scheduleId);
            if (appointments != null && !appointments.isEmpty()) {
                for (Appointment appointment : appointments) {
                    // 获取租客的邮箱地址
                    String userEmail = userMapper.selectById(appointment.getUserId()).getEmail();
                    // 发送邮件通知租客预约已被拒绝
                    sendRejectionEmail(userEmail, rejectReason);
                    // 更新预约的备注为拒绝理由
                    appointment.setRemarks(rejectReason);
                    appointment.setAppointmentStatus("rejected");
                    // 更新预约记录
                    appointmentMapper.updateById(appointment);
                }
            }

            // 更新档期的状态为"不可预约"
            schedule.setStatus(newStatus);
            // 更新档期
            int updated = landlordScheduleMapper.updateById(schedule);
            if (updated <= 0) {
                // 如果更新失败，返回错误
                return new Response<>(500, "档期状态更新失败", null);
            }
        } else {
            // 如果状态不为"booked"，直接更新状态
            schedule.setStatus(newStatus);
            int updated = landlordScheduleMapper.updateById(schedule);
            if (updated <= 0) {
                return new Response<>(500, "档期状态更新失败", null);
            }
        }

        // 更新成功，返回成功响应
        return new Response<>(200, "档期状态更新成功", null);
    }

    private void sendRejectionEmail(String userEmail, String rejectReason) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(userEmail);
        message.setSubject("预约被取消通知");
        message.setText("房东已将您的预约档期设置为不可预约，理由：" + rejectReason);
        message.setFrom(senderEmail);
        mailSender.send(message);
    }

}
